package com.nage.engine;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.opengl.GLSurfaceView;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;

import com.nage.R;
import com.nage.graphics.RenderSystem;
import com.nage.input.InputSystem;
import com.nage.multiplayer.MultiplayerSystem;

public class GameEngine {

	public SimulationSystem ss;
	RenderSystem rs;
	InputSystem is;
	GLSurfaceView view;
	public MultiplayerSystem ms;
	public Context context;
	
	/**
	 * Performs all the initialisation of subsystems of the game engine. Ensuring
	 * that they are correctly linked together, that each one ha started properly
	 * and that the game engine is ready to run.
	 * 
	 * @param c Context from main activity
	 * @throws Exception If something cannot be initialised correctly
	 * 
	 */
	public void initialise(Context c) throws Exception {
		context = c;
		initRenderSystem(c);
		initInputSystem();
		initMultiplayerSystem(c);
		initSimulationSystem(GameGraphBuilder.load(c.getResources().getXml(R.xml.simrate_test), c));
		linkView();
		linkSystems(); 

	}
	
	public void linkView() throws Exception {
		if(is==null || rs==null || view==null) {
			throw new Exception("Subsystems not correctly initialised. Cannot link view");
		}
		view.setRenderer(rs); // render is linked to screen. it is responsible for drawing.
		view.setOnTouchListener(is); // input system linked to screen. it will recieve touch events now.
		

							
		        
		
	}

	/**
	 * Checks that each system has been initialised and then links them all together 
	 * so that they can reference each other correctly.
	 * @throws Exception If a system has not been initialised, they cannot be linked.
	 */
	public void linkSystems() throws Exception {
		if(ms==null || ss==null ) {
			throw new Exception("Subsystems not correctly initialised. Cannot link them together.");
		}

		ms.link(this);
		ss.link(this); // ms <--> ss  They now reference each other.
		is.link(this, ss.isMultiplayer());
		// If the gamegraph specifies that accelerometer should be used, then register
		// the input system to respond to acceleromter events.
		if(ss.getGameGraph().accelerometerOn()) {
			Log.i("GameEngine", "InputSystem registered for Acceleromter events");
			SensorManager sensorMgr = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
			boolean accelSupported = sensorMgr.registerListener(is, 
					sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 
					SensorManager.SENSOR_DELAY_GAME );
		}
		if(ss.isMultiplayer()) {
			ms.start(); // starting multiplayer system will start simulation system once connection is made.
		} else {
			ss.start(); // otherwise just start the simulation straight away.
		}
	}
	

	public void initSimulationSystem(GameGraph gg) {
			ss = new SimulationSystem(gg);
	}

	private void initRenderSystem(Context c) {
		view = new GLSurfaceView(c);
		rs = new RenderSystem(c);


		((Activity) c).requestWindowFeature(Window.FEATURE_NO_TITLE);
		((Activity) c).getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
		((Activity) c).setContentView(view);
	}
	
	private void initInputSystem() {
		is = InputSystem.getInstance();

	}
	
	private void initMultiplayerSystem(Context c) {
		ms = new MultiplayerSystem(c, false);
	}


	public void onPause() {
		view.onPause();
		ss.onPause();
		ms.onPause();
		SensorManager sensorMgr = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
		sensorMgr.unregisterListener(is);	
	}

	public void onResume() {
		view.onResume();
		ss.onResume();
		ms.onResume();
		// If the gamegraph specifies that accelerometer should be used, then register
		// the input system to respond to acceleromter events.
		if(ss.getGameGraph().accelerometerOn()) {
			Log.i("GameEngine", "InputSystem registered for Acceleromter events");
			SensorManager sensorMgr = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
			boolean accelSupported = sensorMgr.registerListener(is, 
					sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 
					SensorManager.SENSOR_DELAY_GAME );
		}
	}

	public void endCurrentSimulation() {
		RenderSystem.unregisterAllDrawables();
		ss.run_simulation = false;
	}
	
}
